home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Format CD 46
/
Amiga Format CD46 (1999-10-20)(Future Publishing)(GB)[!][issue 1999-12].iso
/
-in_the_mag-
/
synth_studies
/
resgrep03b
/
source
/
list.cc
< prev
next >
Wrap
C/C++ Source or Header
|
1999-09-15
|
26KB
|
1,159 lines
//
// Die Implementation der Liste
// In diesem File stehen ALLE Funktionen, da ich es überhaupt nicht mag,
// in der Deklaration einer Klasse massenweise Funktionen stehen zu haben,
// die zum einen verwirren und zum anderen keinen Menschen etwas angehen.
//
// 13.03.1992 Andre geschrieben
// 16.03.1992 Andre display(...) eingebaut.
// 20.03.1992 Andre display(msg,...) eingebaut.
// 23.03.1992 Andre Das Verhalten von 'display()' geändert:
// - wenn das Fenster schon geöffet ist, wird es aktiviert
// und in den Fordergund gebracht,
// - wenn das Fenster versteckt war, wird 'reveal()'
// aufgerufen.
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "list.h"
node::node(char *n, copyway cw, long pr, unsigned long pa)
{
pri = pr;
pack = pa;
if( cw==copy )
name = strdup(n);
else
name = n;
}
node::~node(void)
{
}
node *node::getsucc(void)
{
return succ;
}
node *node::getpred(void)
{
return pred;
}
void node::setsucc(node *s)
{
succ = s;
}
void node::setpred(node *p)
{
pred = p;
}
// Methoden für die Daten
long node::getpri(void)
{
return pri;
}
char *node::getname(void)
{
return name;
}
unsigned long node::getpack(void)
{
return pack;
}
void node::setpri(long p)
{
pri = p;
}
void node::setname(char *n, copyway cw)
{
if( cw==copy )
name = strdup(n);
else
name = n;
}
void node::setpack(unsigned long pa)
{
pack = pa;
}
void node::setpackchar(char *p)
{
char *to;
int i=0;
pack = 0;
to = (char *)pack;
while( *p!='\n' && i++<4 )
*to++=*p++;
}
void node::print(void)
{
if( this!=NULL ) // Ist es ein gültiger Knoten?
printf(" %08lx: Pri: %4d Pack: %08lx Name: '%s'\n",
this, pri, pack, name);
}
// Die Listenmethoden
list::list(void):head(NULL, nocopy),
tail(NULL, nocopy)
{
head.setsucc(&tail);
head.setpred(NULL);
tail.setsucc(NULL);
tail.setpred(&head);
#ifdef amigados
displaywin = NULL;
NewList(&execlist);
g=NULL;
glist=NULL;
menu=NULL;
W_hide=0;
W_xpos=0;
W_ypos=0;
W_height=0;
W_width=0;
W_wintitle=NULL;
W_scrtitle=NULL;
W_mp=NULL;
W_ds=readonly;
W_format=NULL;
change=0;
#endif
}
// Dies ist jetzt gar nicht so einfach, da erst mal die ganze Liste
// freigegeben werden muß.
list::~list(void)
{
node *tmp;
#ifdef amigados
closedis();
#endif
for(node *todel=head.getsucc(); todel->getsucc(); todel=tmp)
{
tmp=todel->getsucc();
delete(todel);
}
}
node *list::getfirst(void)
{
return head.getsucc();
}
node *list::getlast(void)
{
return tail.getpred();
}
// Das Einfügen eines Elements hinter einem anderen
void list::insert(node *p, node *the)
{
// BenutzerInnen sind i.a. DUMM, deshalb wird hier ALLES mögliche
// abgefragt.
if( the==NULL )
return;
#ifdef amigados
// Wenn die Liste nicht leer ist, leer machen!
if( execlist.lh_Head->ln_Succ!=NULL )
freeexeclist();
#endif
// Ist 'p' gleich NULL wird der Knoten ganz vorne eingekettet.
// (oder wenn p gleich dem Header ist)
if( p==NULL || p==&head )
{
this->addhead(the);
return;
}
the->setsucc(p->getsucc());
the->setpred(p);
p->setsucc(the);
(the->getsucc())->setpred(the);
}
// Das Löschen eines Knotens
void list::remove(node *n)
{
#ifdef amigados
if( execlist.lh_Head->ln_Succ!=NULL )
freeexeclist();
#endif
if( n==NULL || n->getsucc()==NULL || n->getpred()==NULL )
return;
(n->getpred())->setsucc(n->getsucc());
(n->getsucc())->setpred(n->getpred());
n->setpred(NULL);
n->setsucc(NULL);
}
void list::addhead(node *n)
{
#ifdef amigados
if( execlist.lh_Head->ln_Succ!=NULL )
freeexeclist();
#endif
n->setsucc(head.getsucc());
n->setpred(&head);
head.setsucc(n);
(n->getsucc())->setpred(n);
}
void list::addtail(node *n)
{
#ifdef amigados
if( execlist.lh_Head->ln_Succ!=NULL )
freeexeclist();
#endif
n->setsucc(&tail);
n->setpred(tail.getpred());
tail.setpred(n);
(n->getpred())->setsucc(n);
}
node *list::remhead(void)
{
node *n;
#ifdef amigados
if( execlist.lh_Head->ln_Succ!=NULL )
freeexeclist();
#endif
if( head.getsucc()==&tail ) // Liste leer?
return NULL;
n=head.getsucc();
head.setsucc(n->getsucc());
(n->getsucc())->setpred(&head);
n->setsucc(NULL);
n->setpred(NULL);
return n;
}
node *list::remtail(void)
{
node *n;
#ifdef amigados
if( execlist.lh_Head->ln_Succ!=NULL )
freeexeclist();
#endif
if( head.getsucc()==&tail ) // Liste leer?
return NULL;
n=tail.getpred();
tail.setpred(n->getpred());
(n->getpred())->setsucc(&tail);
n->setsucc(NULL);
n->setpred(NULL);
return n;
}
// Die speziellen Einfügekommandos
void list::enqueuepri(node *n)
{
#ifdef amigados
if( execlist.lh_Head->ln_Succ!=NULL )
freeexeclist();
#endif
// Wenn die Liste leer ist, wird der Knoten mit 'addhead()' eingefügt
if( head.getsucc()==&tail )
{
this->addhead(n);
return;
}
// Sonst wird das erste Element gesucht, das eine höhere Priorität hat
for(node *i=head.getsucc(); i->getsucc(); i=i->getsucc())
if( i->getpri()>n->getpri() )
{
this->insert(i->getpred(),n);
return;
}
// Wenn es ganz durchgelaufen ist, gibt es keine höhere Priorität. Der
// Knoten wird ans Listenende geschrieben.
this->addtail(n);
}
void list::enqueuename(node *n)
{
#ifdef amigados
if( execlist.lh_Head->ln_Succ!=NULL )
freeexeclist();
#endif
// Wenn die Liste leer ist, wird der Knoten mit 'addhead()' eingefügt.
// Außerdem stehen alle mit leerem Namen ganz vorne.
if( head.getsucc()==&tail || n->getname()==NULL )
{
this->addhead(n);
return;
}
// Sonst wird das erste Element gesucht, das einen Namen besitzt, der
// alphabetisch später kommt.
for(node *i=head.getsucc(); i->getsucc(); i=i->getsucc())
if( strcmp(i->getname(),n->getname())>0 )
{
this->insert(i->getpred(),n);
return;
}
// Wenn es ganz durchgelaufen ist, gibt es keine höhere Priorität. Der
// Knoten wird ans Listenende geschrieben.
this->addtail(n);
}
void list::enqueuepack(node *n)
{
#ifdef amigados
if( execlist.lh_Head->ln_Succ!=NULL )
freeexeclist();
#endif
// Wenn die Liste leer ist, wird der Knoten mit 'addhead()' eingefügt
if( head.getsucc()==&tail )
{
this->addhead(n);
return;
}
// Sonst wird das erste Element gesucht, das einen Namen besitzt, der
// alphabetisch später kommt.
for(node *i=head.getsucc(); i->getsucc(); i=i->getsucc())
if( i->getpack()>n->getpack() )
{
this->insert(i->getpred(),n);
return;
}
// Wenn es ganz durchgelaufen ist, gibt es keine höhere Priorität. Der
// Knoten wird ans Listenende geschrieben.
this->addtail(n);
}
// Die Suchkommandos
node *list::findpri(long p)
{
for(node *i=head.getsucc(); i->getsucc(); i=i->getsucc())
if( i->getpri()==p )
return i;
return NULL;
}
node *list::findname(char *n)
{
for(node *i=head.getsucc(); i->getsucc(); i=i->getsucc())
if( strcmp(i->getname(),n)==0 )
return i;
return NULL;
}
node *list::findpack(unsigned long pa)
{
for(node *i=head.getsucc(); i->getsucc(); i=i->getsucc())
if( i->getpack()==pa )
return i;
return NULL;
}
// Jetzt kommt so ungefähr das schwierigste: eine dopplet verkettete Liste
// sortieren.
void list::sortpri(void)
{
node *tmpi, *tmpj;
#ifdef amigados
if( execlist.lh_Head->ln_Succ!=NULL )
freeexeclist();
#endif
for(node *i=head.getsucc(); i->getsucc(); i=tmpi)
{
tmpi=i->getsucc();
for(node *j=tail.getpred(); j!=i; j=tmpj)
{
tmpj=j->getpred();
// Es werden die Elemente 'j' und 'Vorgänger von j' verglichen
// und (vielleicht) vertauscht.
if( j->getpri()<tmpj->getpri() )
{
// Darauf achten, daß tmpi und i richtig gesetzt bleibt
if( tmpi==tmpj )
tmpi=tmpi->getsucc();
else if( tmpi==j )
{
i=j;
tmpi=tmpj;
}
// Zuerst die 'succ' richtig setzen
(tmpj->getpred())->setsucc(j);
tmpj->setsucc(j->getsucc());
j->setsucc(tmpj);
// Dann -- mit Hilfe der greade gesetzten 'succ' -- die 'pred'
// richtig setzen.
(tmpj->getsucc())->setpred(tmpj);
j->setpred(tmpj->getpred());
tmpj->setpred(j);
// j und tmpj wieder richtig setzten.
tmpj=j;
}
}
}
}
void list::sortname(void)
{
node *tmpi, *tmpj;
#ifdef amigados
if( execlist.lh_Head->ln_Succ!=NULL )
freeexeclist();
#endif
for(node *i=head.getsucc(); i->getsucc(); i=tmpi)
{
tmpi=i->getsucc();
for(node *j=tail.getpred(); j!=i; j=tmpj)
{
tmpj=j->getpred();
// Es werden die Elemente 'j' und 'Vorgänger von j' verglichen
// und (vielleicht) vertauscht.
if( (j->getname()==NULL && tmpj->getname()!=NULL )
|| (strcmp(j->getname(),tmpj->getname())<0) )
{
// Darauf achten, daß tmpi und i richtig gesetzt bleibt
if( tmpi==tmpj )
tmpi=tmpi->getsucc();
else if( tmpi==j )
{
i=j;
tmpi=tmpj;
}
// Zuerst die 'succ' richtig setzen
(tmpj->getpred())->setsucc(j);
tmpj->setsucc(j->getsucc());
j->setsucc(tmpj);
// Dann -- mit Hilfe der greade gesetzten 'succ' -- die 'pred'
// richtig setzen.
(tmpj->getsucc())->setpred(tmpj);
j->setpred(tmpj->getpred());
tmpj->setpred(j);
// j und tmpj wieder richtig setzten.
tmpj=j;
}
}
}
}
void list::sortpack(void)
{
node *tmpi, *tmpj;
#ifdef amigados
if( execlist.lh_Head->ln_Succ!=NULL )
freeexeclist();
#endif
for(node *i=head.getsucc(); i->getsucc(); i=tmpi)
{
tmpi=i->getsucc();
for(node *j=tail.getpred(); j!=i; j=tmpj)
{
tmpj=j->getpred();
// Es werden die Elemente 'j' und 'Vorgänger von j' verglichen
// und (vielleicht) vertauscht.
if( j->getpack()<tmpj->getpack() )
{
// Darauf achten, daß tmpi und i richtig gesetzt bleibt
if( tmpi==tmpj )
tmpi=tmpi->getsucc();
else if( tmpi==j )
{
i=j;
tmpi=tmpj;
}
// Zuerst die 'succ' richtig setzen
(tmpj->getpred())->setsucc(j);
tmpj->setsucc(j->getsucc());
j->setsucc(tmpj);
// Dann -- mit Hilfe der greade gesetzten 'succ' -- die 'pred'
// richtig setzen.
(tmpj->getsucc())->setpred(tmpj);
j->setpred(tmpj->getpred());
tmpj->setpred(j);
// j und tmpj wieder richtig setzten.
tmpj=j;
}
}
}
}
void list::print(void)
{
int i=0;
printf("Ausgabe der Liste:\n");
for(node *n=head.getsucc(); n->getsucc(); n=n->getsucc())
printf("%3d: Pri: %3d Pack: %08lx Name: '%s'\n",
i++, n->getpri(), n->getpack(), n->getname());
printf("Ende der Liste.\n\n");
}
// Ab jetzt kommen nur noch AmigaOS spezifische Sachen.
#ifdef amigados
void list::freeexeclist(void)
{
struct Node *tmp;
if( execlist.lh_Head->ln_Succ == NULL )
return;
for(struct Node *en=execlist.lh_Head; en->ln_Succ; en=tmp)
{
tmp=en->ln_Succ;
free(en->ln_Name);
free(en);
}
NewList(&execlist);
}
char *list::pack2string(unsigned long pa)
{
static char to[5];
char *from = (char *)&pa;
to[0]=from[0];
to[1]=from[1];
to[2]=from[2];
to[3]=from[3];
to[4]='\0';
return to;
}
void list::doformat(char *buffer, char *format, node *n)
{
if( format==NULL )
return;
while( *format!='\0' )
{
switch( *format )
{
case 'a': // Packed als Zahl
sprintf(buffer,"%08lx",n->getpack());
buffer+=8;
break;
case 'i': // Packed als Text
sprintf(buffer,"%4s",pack2string(n->getpack()));
buffer+=4;
break;
case 'n': // Name
sprintf(buffer,"%s",n->getname());
buffer+=strlen(n->getname());
break;
case 'p': // Priorität
sprintf(buffer,"%6d",n->getpri());
buffer+=6;
break;
default:
break;
}
*buffer++=' ';
format++;
}
*buffer='\0';
}
node *list::num2node(int num)
{
node *n;
if( num<0 )
return NULL;
for(n=head.getsucc(); n->getsucc() && num!=0; n=n->getsucc(), num--)
;
if( num==0 )
return n;
else
return NULL;
}
void list::makeexeclist(char *format)
{
char buffer[1024]; // Länger darf keine Zeile werden!
if( execlist.lh_Head->ln_Succ!=NULL )
freeexeclist();
for(node *n=head.getsucc(); n->getsucc(); n=n->getsucc())
{
struct Node *node;
if( (node=malloc(sizeof(struct Node))) == NULL )
{
fprintf(stderr,"FEHLER: Kann keinen Speicher"
" für die ExecListe bekommen.\n");
return;
}
doformat(buffer,format,n);
node->ln_Name=strdup(buffer);
AddTail(&execlist,node);
}
}
// Und die Display-Funktionen
int list::domsg(struct IntuiMessage *msg)
{
int num=0;
switch( msg->Class )
{
case IDCMP_INTUITICKS:
case IDCMP_MOUSEBUTTONS:
case IDCMP_MOUSEMOVE:
case IDCMP_GADGETDOWN:
case IDCMP_REFRESHWINDOW:
break;
case IDCMP_CLOSEWINDOW:
return -1;
break;
case IDCMP_GADGETUP:
return msg->Code;
break;
case IDCMP_MENUPICK:
if(msg->Code!=MENUNULL)
return -1;
break;
default:
fprintf(stderr,"FEHLER: unbekannte Message.\n");
break;
}
return -2;
}
node *list::display(dsply ds, char *format, int width, int height,
int xpos, int ypos, char *wintitle, char *scrtitle)
{
struct IntuiMessage theIMsg, *imsg;
struct TextAttr topaz8 = {
( STRPTR )"topaz.font", 8, 0x00, 0x01 };
struct TagItem WindowTags[] =
{
WA_Left, (ULONG) xpos,
WA_Top, (ULONG) ypos,
WA_Width, (ULONG) width*8+20+27, // Benutze 'topaz 8'
WA_Height, (ULONG) height*8+23,
WA_IDCMP, (ULONG) IDCMP_MOUSEBUTTONS | IDCMP_MOUSEMOVE |
IDCMP_GADGETDOWN | IDCMP_GADGETUP |
IDCMP_MENUPICK | IDCMP_CLOSEWINDOW |
IDCMP_INTUITICKS |
IDCMP_REFRESHWINDOW,
WA_Flags, (ULONG) WFLG_DRAGBAR | WFLG_DEPTHGADGET |
WFLG_CLOSEGADGET | WFLG_SMART_REFRESH |
WFLG_ACTIVATE,
WA_Gadgets, (ULONG) 0l,
WA_Title, (ULONG) wintitle,
WA_ScreenTitle, (ULONG) scrtitle,
WA_MinWidth, (ULONG) 67,
WA_MinHeight, (ULONG) 21,
WA_MaxWidth, (ULONG) 640,
WA_MaxHeight, (ULONG) 256,
WA_AutoAdjust, 1l,
TAG_DONE
};
struct NewGadget ng;
struct NewMenu NewMenu[] =
{
NM_TITLE, "Control", 0l, 0, 0, 0l,
NM_ITEM, "Close Window", "K", 0, 0, 0l,
NM_END, 0l, 0l, 0, 0l, 0l
};
makeexeclist(format);
if ( NOT( menu = CreateMenus( NewMenu, GTMN_FrontPen, 0l, TAG_DONE )))
return( NULL );
LayoutMenus( menu, VisualInfo, GTMN_TextAttr, &topaz8, TAG_DONE );
if ( NOT( g = CreateContext( &glist )))
return( NULL );
ng.ng_LeftEdge = 10;
ng.ng_TopEdge = 14;
ng.ng_Width = width*8+28;
ng.ng_Height = height*8+4;
ng.ng_GadgetText = 0l;
ng.ng_TextAttr = &topaz8;
ng.ng_GadgetID = 0;
ng.ng_Flags = 0;
ng.ng_VisualInfo = VisualInfo;
if( ds==readonly )
g = CreateGadget( LISTVIEW_KIND, g, &ng,
GTLV_Labels, &execlist,
GTLV_ReadOnly, TRUE,
TAG_DONE );
else
g = CreateGadget( LISTVIEW_KIND, g, &ng,
GTLV_Labels, &execlist,
TAG_DONE );
if ( NOT g )
return( NULL );
WindowTags[ 6 ].ti_Data = (ULONG)glist;
if ( NOT( displaywin = OpenWindowTagList( 0l, WindowTags )))
return( NULL );
SetMenuStrip( displaywin, menu );
GT_RefreshWindow( displaywin, 0l );
for(;;)
{
int number=-1, num;
Wait( 1UL<<(unsigned long)(displaywin->UserPort->mp_SigBit) );
while( (imsg=GT_GetIMsg(displaywin->UserPort)) != NULL )
{
theIMsg=*imsg;
GT_ReplyIMsg(imsg);
if( (num=domsg(&theIMsg))>=-1 )
{
freeexeclist();
ClearMenuStrip( displaywin );
FreeMenus( menu );
CloseWindow( displaywin );
FreeGadgets( glist );
glist=NULL;
g=NULL;
displaywin=NULL;
return num2node(num);
}
}
}
}
// Die weitaus aufwendigsten Funktionen:
// Darstellung, Message-Handling, Verstecken, Revealing und Schliessen
// von einem Listenfenster in einer Multi-Window Umgebung.
// Return Codes:
// 0 - Fenster war geschlossen und ist ordnungsgemäß geöffnet worden
// 1 - Fenster war versteckt und ist mit 'reveal()' hervoegeholt worden.
// 2 - Fenster war geöffnet und ist nach vorn geholt und aktiviert worden.
// 11 - CreateContext hat Fehler zurückgegeben.
// 12 - CreateGadget hat Fehler zurückgegeben.
// 13 - OpenWindow hat Fehler zurückgegeben.
int list::display(struct MsgPort *up, struct Menu *men,
dsply ds, char *format, int width, int height,
int xpos, int ypos, char *wintitle, char *scrtitle)
{
struct TextAttr topaz8 = {
( STRPTR )"topaz.font", 8, 0x00, 0x01 };
struct TagItem WindowTags[] =
{
WA_Left, (ULONG) xpos,
WA_Top, (ULONG) ypos,
WA_Width, (ULONG) width*8+20+27, // Benutze 'topaz 8'
WA_Height, (ULONG) height*8+23,
WA_IDCMP, (ULONG) 0l,
WA_Flags, (ULONG) WFLG_DRAGBAR | WFLG_DEPTHGADGET |
WFLG_CLOSEGADGET | WFLG_SMART_REFRESH |
WFLG_ACTIVATE,
WA_Gadgets, (ULONG) 0l,
WA_Title, (ULONG) (W_wintitle=strdup(wintitle)),
WA_ScreenTitle, (ULONG) (W_scrtitle=strdup(scrtitle)),
WA_MinWidth, (ULONG) 67,
WA_MinHeight, (ULONG) 21,
WA_MaxWidth, (ULONG) 640,
WA_MaxHeight, (ULONG) 256,
WA_AutoAdjust, 1l,
TAG_DONE
};
struct NewGadget ng;
if( displaywin!=NULL ) // Falls schon geöffnet!
{
ActivateWindow(displaywin);
WindowToFront(displaywin);
return 2;
}
if( W_hide==1 ) // Wenn das Fenster versteckt ist, kann es nicht
// geöffnet werden.
{
reveal();
return 1;
}
// Variablen setzten, die noch für das 'hide()' und 'reveal()'
// benötigt werden.
// W_wintitle = strdup(wintitle);
// W_scrtitle = strdup(scrtitle);
W_ds = ds;
W_format = format;
W_mp = up;
if( execlist.lh_Head->ln_Succ!=NULL )
freeexeclist();
makeexeclist(format);
if ( NOT( g = CreateContext( &glist )))
return 11;
ng.ng_LeftEdge = 10;
ng.ng_TopEdge = 14;
ng.ng_Width = width*8+28;
ng.ng_Height = height*8+4;
ng.ng_GadgetText = 0l;
ng.ng_TextAttr = &topaz8;
ng.ng_GadgetID = 0;
ng.ng_Flags = 0;
ng.ng_VisualInfo = VisualInfo;
if( ds==readonly )
g = CreateGadget( LISTVIEW_KIND, g, &ng,
GTLV_Labels, &execlist,
GTLV_ReadOnly, TRUE,
TAG_DONE );
else
g = CreateGadget( LISTVIEW_KIND, g, &ng,
GTLV_Labels, &execlist,
TAG_DONE );
if ( NOT g )
return 12;
WindowTags[ 6 ].ti_Data = (ULONG)glist;
if ( NOT( displaywin = OpenWindowTagList( 0l, WindowTags )))
return 13;
if( up==NULL )
return 0;
displaywin->UserPort=up;
ModifyIDCMP(displaywin,
(ULONG) IDCMP_MOUSEBUTTONS | IDCMP_MOUSEMOVE |
IDCMP_GADGETDOWN | IDCMP_GADGETUP |
IDCMP_MENUPICK | IDCMP_CLOSEWINDOW |
IDCMP_INTUITICKS | IDCMP_REFRESHWINDOW);
menu=men;
if( menu!=NULL )
SetMenuStrip( displaywin, menu );
GT_RefreshWindow( displaywin, 0l );
return 0;
}
node *list::checkdis(struct IntuiMessage *msg)
{
int nummer;
// Ist diese Meldung für mich bestimmt?
if( msg->IDCMPWindow!=displaywin )
return NULL;
msg->IDCMPWindow = NULL;
if( (nummer=domsg(msg))==-1 ) // Window Close
{
hide();
return NULL;
}
if( nummer>=0 )
return num2node(nummer);
return NULL;
}
void printMessages(struct MsgPort *m)
{
struct Node *msg;
for(msg=m->mp_MsgList.lh_Head;
msg->ln_Succ; msg=msg->ln_Succ)
{
printf("Message at %08lx:\n",msg);
printf(" Type: %2d Pri: %3d Name: '%s'\n",
msg->ln_Type, msg->ln_Pri, msg->ln_Name);
printf(" ReplyPort: %08lx Length: %4d\n",
((struct Message *)msg)->mn_ReplyPort,
((struct Message *)msg)->mn_Length);
printf(" Class: %08lx Code: %04x Window: %08lx\n",
((struct IntuiMessage *)msg)->Class,
((struct IntuiMessage *)msg)->Code,
((struct IntuiMessage *)msg)->IDCMPWindow);
}
printf("Not Waiting ---> ");
}
// Aus den Autodocs:
/* remove and reply all IntuiMessages on a port that
* have been sent to a particular window
* (note that we don't rely on the ln_Succ pointer
* of a message after we have replied it)
*/
void StripIntuiMessages( struct MsgPort *mp, struct Window *win )
{
struct IntuiMessage *msg;
struct Node *succ;
msg = (struct IntuiMessage *) mp->mp_MsgList.lh_Head;
while( succ = msg->ExecMessage.mn_Node.ln_Succ )
{
if( msg->IDCMPWindow == win )
{
/* Intuition is about to free this message.
* Make sure that we have politely sent it back.
*/
Remove( msg );
ReplyMsg( msg );
}
msg = (struct IntuiMessage *) succ;
}
}
/* these functions close an Intuition window
* that shares a port with other Intuition
* windows or IPC customers.
*
* We are careful to set the UserPort to
* null before closing, and to free
* any messages that it might have been
* sent.
*/
void CloseWindowSafely( struct Window *win )
{
struct MsgPort *mp=win->UserPort;
/* we forbid here to keep out of race conditions with Intuition */
Forbid();
/* send back any messages for this window
* that have not yet been processed
*/
StripIntuiMessages( win->UserPort, win );
/* clear UserPort so Intuition will not free it */
win->UserPort = NULL;
/* tell Intuition to stop sending more messages */
ModifyIDCMP( win, 0L );
/* turn multitasking back on */
Permit();
/* and really close the window */
CloseWindow( win );
}
// Schliesse ein Fenster
void list::closedis(void)
{
if( execlist.lh_Head->ln_Succ!=NULL )
freeexeclist();
if( menu!=NULL )
{
ClearMenuStrip( displaywin );
menu=NULL;
}
if( displaywin!=NULL )
{
CloseWindowSafely( displaywin );
displaywin=NULL;
}
if( glist!=NULL )
{
FreeGadgets( glist );
glist=NULL;
}
g=NULL;
// Dann noch die Window-Variablen initialisieren:
W_hide=0;
W_xpos=0;
W_ypos=0;
W_height=0;
W_width=0;
W_wintitle=NULL;
W_scrtitle=NULL;
W_mp=NULL;
W_ds=readonly;
W_format=NULL;
}
// Versteckt ein Fenster
void list::hide(void)
{
if( W_hide==1 ) // Fenster ist schon versteckt
return;
if( displaywin==NULL ) // Fenster ist versteckt
return;
// Zuerst einmal die Parameter für ein 'reveal()' richtig setzten.
W_hide = 1; // Fenster ist versteckt.
W_xpos = displaywin->LeftEdge;
W_ypos = displaywin->TopEdge;
W_height = displaywin->Height;
W_width = displaywin->Width;
// Die ExecList wird NICHT freigegeben, in der Hoffnung sie nocheinmal
// gebrauchen zu können.
// Der Rest entspricht (fast) dem 'closedis()'.
if( menu!=NULL )
ClearMenuStrip( displaywin );
if( displaywin!=NULL )
{
CloseWindowSafely( displaywin );
displaywin=NULL;
}
if( glist!=NULL )
{
FreeGadgets( glist );
glist=NULL;
}
g=NULL;
}
// Und entsprechend dem 'display()' das 'reveal()':
int list::reveal(void)
{
struct TextAttr topaz8 = {
( STRPTR )"topaz.font", 8, 0x00, 0x01 };
struct TagItem WindowTags[] =
{
WA_Left, (ULONG) W_xpos,
WA_Top, (ULONG) W_ypos,
WA_Width, (ULONG) W_width,
WA_Height, (ULONG) W_height,
WA_IDCMP, (ULONG) 0l,
WA_Flags, (ULONG) WFLG_DRAGBAR | WFLG_DEPTHGADGET |
WFLG_CLOSEGADGET | WFLG_SMART_REFRESH |
WFLG_ACTIVATE,
WA_Gadgets, (ULONG) 0l,
WA_Title, (ULONG) W_wintitle,
WA_ScreenTitle, (ULONG) W_scrtitle,
WA_MinWidth, (ULONG) 67,
WA_MinHeight, (ULONG) 21,
WA_MaxWidth, (ULONG) 640,
WA_MaxHeight, (ULONG) 256,
WA_AutoAdjust, 1l,
TAG_DONE
};
struct NewGadget ng;
if( W_hide==0 ) // Fenster ist gar nicht versteckt!
return 6;
if( displaywin!=NULL ) // Falls schon geöffnet!
return 5;
if( execlist.lh_Head->ln_Succ==NULL )
makeexeclist(W_format);
if ( NOT( g = CreateContext( &glist )))
return 1;
ng.ng_LeftEdge = 10;
ng.ng_TopEdge = 14;
ng.ng_Width = W_width-19;
ng.ng_Height = W_height-19;
ng.ng_GadgetText = 0l;
ng.ng_TextAttr = &topaz8;
ng.ng_GadgetID = 0;
ng.ng_Flags = 0;
ng.ng_VisualInfo = VisualInfo;
if( W_ds==readonly )
g = CreateGadget( LISTVIEW_KIND, g, &ng,
GTLV_Labels, &execlist,
GTLV_ReadOnly, TRUE,
TAG_DONE );
else
g = CreateGadget( LISTVIEW_KIND, g, &ng,
GTLV_Labels, &execlist,
TAG_DONE );
if ( NOT g )
return 2;
WindowTags[ 6 ].ti_Data = (ULONG)glist;
if ( NOT( displaywin = OpenWindowTagList( 0l, WindowTags )))
return 3;
if( W_mp==NULL )
return 4;
displaywin->UserPort=W_mp;
ModifyIDCMP(displaywin,
(ULONG) IDCMP_MOUSEBUTTONS | IDCMP_MOUSEMOVE |
IDCMP_GADGETDOWN | IDCMP_GADGETUP |
IDCMP_MENUPICK | IDCMP_CLOSEWINDOW |
IDCMP_INTUITICKS | IDCMP_REFRESHWINDOW);
if( menu!=NULL )
SetMenuStrip( displaywin, menu );
GT_RefreshWindow( displaywin, 0l );
W_hide=0;
return 0;
}
// Die 'execlist' von dem Fenster detachen.
void list::start_change(void)
{
if( change==1 ) // Wenn die Liste schon detached ist,
return;
change=0;
if( displaywin==NULL ) // oder es gar kein Fenster gibt,
return;
if( W_hide==1 ) // oder das Fenster versteckt ist.
return;
GT_SetGadgetAttrs(g, displaywin, NULL, GTLV_Labels, ~0);
freeexeclist();
change=1;
}
void list::end_change(void)
{
if( change==0 ) // Wenn vorher gar nicht 'start_change()' aufgerufen wurde
return;
change=0;
if( displaywin==NULL ) // oder das Fenster gar nicht geöffnet ist,
return;
if( W_hide==1 ) // oder das Fenster versteckt ist.
return;
freeexeclist();
makeexeclist(W_format);
GT_SetGadgetAttrs(g, displaywin, NULL, GTLV_Labels, &execlist);
}
struct MsgPort *list::getmp(void)
{
return W_mp;
}
struct Menu *list::getmenu(void)
{
return menu;
}
struct Window *list::getwin(void)
{
return displaywin;
}
#endif